home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Just Call Me Internet
/
Just Call Me Internet.iso
/
prog
/
atari
/
c
/
nos042_s
/
dialer.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-11-03
|
32KB
|
1,376 lines
/* Automatic SLIP/PPP line dialer.
*
* Copyright 1991 Phil Karn, KA9Q
*
* Mar '91 Bill Simpson & Glenn McGregor
* completely re-written;
* human readable control file;
* includes wait for string, and speed sense;
* dials immediately when invoked.
* May '91 Bill Simpson
* re-ordered command line;
* allow dial only;
* allow inactivity timeout without ping.
* Sep '91 Bill Simpson
* Check known DTR & RSLD state for redial decision
* 11 Mar 92 Giles Todd
* Add "configure:" and "execute:" sections and new commands.
* 19 Mar 92 Giles Todd
* Fix failure string processing.
* 31 May 92 Giles Todd
* Fix empty configure string problems.
* 02 Jun 92 Giles Todd
* Fix dial session cancel bug.
*
$Id: dialer.c 1.13 94/01/04 14:09:02 ROOT_DOS Exp $
*
* 04 Aug 92 1.6 GT No change.
* 09 Aug 92 1.7 GT Inline dialing.
* 17 Aug 92 1.8 GT Allow escape from inline dial.
* 13 Sep 92 1.9 CMS Ignore script lines consisting only of a newline.
* 03 Apr 93 1.11 GT Fix order of calls.
* 08 May 93 1.12 GT Fix warnings.
* Improve dialer interruption.
* 10 Dec 93 1.13 GT Don't obscure modem messages.
*
* ATARI version by David Nash - dnash@chaos.demon.co.uk
*
* Include st_asy.h in place of 8250.h
*
* 04.11.94 DFN dodial_status correct call to iostatus function
*
*/
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include "global.h"
#include "config.h"
#include "mbuf.h"
#include "timer.h"
#include "proc.h"
#include "iface.h"
#include "netuser.h"
#ifdef ATARI
#include "st_asy.h"
#else
#include "8250.h"
#endif
#include "asy.h"
#include "tty.h"
#include "session.h"
#include "socket.h"
#include "cmdparse.h"
#include "devparam.h"
#include "icmp.h"
#include "files.h"
#include "main.h"
#include "trace.h"
#include "hardware.h"
#include "commands.h"
extern struct cmds far Cmds[];
#define MIN_INTERVAL 5L
typedef struct item ITEM;
struct item
{
char *data; /* some text */
ITEM *next; /* -> next in list */
};
static int redial __ARGS((struct iface *ifp, char *file));
static int cfg_init __ARGS((int argc, char *argv[], void *p));
static int cfg_dial_cmd __ARGS((int argc, char *argv[], void *p));
static int cfg_ld_code __ARGS((int argc, char *argv[], void *p));
static int cfg_number __ARGS((int argc, char *argv[], void *p));
static int cfg_retries __ARGS((int argc, char *argv[], void *p));
static int dodial_control __ARGS((int argc, char *argv[], void *p));
static int dodial_dial __ARGS((int argc, char *argv[], void *p));
static int dodial_init __ARGS((int argc, char *argv[], void *p));
static int dodial_send __ARGS((int argc, char *argv[], void *p));
static int dodial_speed __ARGS((int argc, char *argv[], void *p));
static int dodial_status __ARGS((int argc, char *argv[], void *p));
static int dodial_wait __ARGS((int argc, char *argv[], void *p));
static int dodial_cwait __ARGS((int argc, char *argv[], void *p));
static int __stdargs dodialer __ARGS((int argc, char *argv[], void *p));
static int __stdargs do_inline __ARGS((int argc, char *argv[], void *p));
static void add_cmd __ARGS((ITEM **hdr, ITEM **ptr, char *buf));
static char *next_cmd __ARGS((char *buf, ITEM **ptr));
static void clean_up __ARGS((void));
static void clean __ARGS((ITEM **hdr));
static int internal_send __ARGS((char *ptr, void *p));
static int asy_kb_poll __ARGS((int dev));
static struct cmds dial_cmds[] =
{
{ "control", dodial_control, 0, 2, "control up | down" },
{ "dial", dodial_dial, 0, 0, "dial" },
{ "init", dodial_init, 0, 0, "init" },
{ "send", dodial_send, 0, 2,
"send \"string\" [<milliseconds>]" },
{ "speed", dodial_speed, 0, 2, "speed <bps>" },
{ "status", dodial_status, 0, 2, "status up | down" },
{ "wait", dodial_wait, 0, 2,
"wait <milliseconds> [ \"string\" [speed] ]" },
{ "cwait", dodial_cwait, 0, 2,
"cwait <milliseconds> [ \"success string\" \"failure string\" [, \"failure string\" ...] [speed] ]" },
{ NULLCHAR, NULLFP, 0, 0, "Unknown command" },
};
static struct cmds cfg_cmds[] =
{
{ "init", cfg_init, 0, 2, "init \"string\"" },
{ "dial_cmd", cfg_dial_cmd, 0, 2, "dial_cmd \"string\"" },
{ "ld_code", cfg_ld_code, 0, 2, "ld_code \"string\"" },
{ "number", cfg_number, 0, 2, "number \"string\"" },
{ "retries", cfg_retries, 0, 2, "retries <count>" },
{ NULLCHAR, NULLFP, 0, 0, "Unknown command" },
};
static char cfg_intro[] = "configure:";
static char exe_intro[] = "execute:";
static int configuring = 0; /* nz - found configuration section */
static char *init = NULL; /* initialization string */
static char *dial_cmd = NULL; /* modem dial command */
static char *ld_code = NULL; /* long distance code */
static ITEM *number = NULL; /* telephone numbers */
static ITEM *nr_ptr = NULL; /* -> current number */
static unsigned retries = 1; /* number of dial retries */
static ITEM *cfg_cmd = NULL; /* configuration commands */
static ITEM *exe_cmd = NULL; /* script commands */
static ITEM *cmd_ptr = NULL; /* -> current script command */
static int dial_inline = 0; /* nz - dial inline */
static int interrupted; /* nz - dial interrupted */
/****************************************************************************
* do_inline *
* Toggles the "inline dialing" flag and sets and resets the dialer task's *
* stack size. *
****************************************************************************/
#ifndef ATARI
#define DIALER_STACK 512
#else
#define DIALER_STACK 2512
#endif
int __stdargs do_inline (argc, argv, p)
int argc;
char *argv[];
void *p;
{
int rc; /* return value */
struct cmds *cmd_ptr; /* -> command structure */
/* Set / reset / report flag value. */
rc = setbool (&dial_inline, "Inline dialing", argc, argv);
/* Set the dialer stack size. */
cmd_ptr = Cmds;
while (cmd_ptr->name != NULLCHAR)
{
if (strcmp (cmd_ptr->name, "dialer") == 0)
break;
cmd_ptr++;
}
if (dial_inline == 0)
cmd_ptr->stksize = DIALER_STACK; /* asynch process */
else
cmd_ptr->stksize = 0; /* inline process */
return (rc);
} /* int do_inline (argc, argv, p) */
/* dial <iface> <filename> [ <seconds> [ <pings> [<hostid>] ] ]
* <iface> must be asy type
* <filename> contains commands which are executed.
* missing: kill outstanding dialer.
* <seconds> interval to check for activity on <iface>.
* (if 0 then demand dial)
* <pings> number of missed pings before redial.
* <hostid> interface to ping.
*/
int __stdargs dodialer (argc, argv, p)
int argc;
char *argv[];
void *p;
{
struct iface *ifp;
struct asy *ap;
int32 interval = 0L; /* in seconds */
int32 last_wait = 0L;
int32 target = 0L;
int pings = 0;
int countdown;
char *filename;
char *ifn;
int result;
int s;
int exit_on_fail;
if ((ifp = if_lookup (argv[1])) == NULLIF)
{
tprintf ("Interface %s unknown\n", argv[1]);
return 1;
}
if (ifp->dev >= ASY_MAX || Asy[ifp->dev].iface != ifp)
{
tprintf ("Interface %s not asy port\n", argv[1]);
return 1;
}
if (ifp->supv != NULLPROC)
{
while (ifp->supv != NULLPROC)
{
alert (ifp->supv, EABORT);
pwait (NULL);
}
tprintf ("dialer terminated on %s\n", argv[1]);
}
if (argc < 3)
{
/* just terminating */
return 0;
}
chname (Curproc, ifn = if_name (ifp, " dialer"));
free (ifn);
#ifdef ATARI
if (!access(argv[2], 0)) /* check if file exists */
filename = argv[2];
else
#endif
filename = rootdircat (argv[2]);
ap = &Asy[ ifp->dev ];
if (argc == 4 && strcmp(argv[3], "failexit") == 0)
exit_on_fail = 1;
else exit_on_fail = 0;
/* handle minimal command (just thru filename) */
if (argc < 4 || exit_on_fail)
{
/* just dialing */
ifp->supv = Curproc; /* so that it can be cancelled */
result = redial (ifp, filename);
if (filename != argv[2])
free (filename);
ifp->supv = NULLPROC;
if (result != 0 && exit_on_fail == 1)
doexit (0, NULL, NULL);
return result;
}
/* get polling interval (arg 3) */
else if (strcmp(argv[3], "demand")
&& (interval = atol (argv[3])) <= MIN_INTERVAL)
{
tprintf ("interval must be > %d seconds\n", MIN_INTERVAL);
return 1;
}
if (strcmp(argv[3], "demand") == 0)
/* Interval of 0, so we're demand dialing */
{
int32 backoff;
tprintf("Demand dialing enabled\n");
backoff = 4;
ifp->supv = Curproc; /* so that it can be cancelled */
ifp->dial_me = 0;
while (!main_exit)
{
alarm (2000L);
if (pwait (& (ifp->supv)) == EABORT)
break;
alarm (0L);
if (ifp->dial_me)
{
if (ap->dtr_usage == FOUND_DOWN ||
ap->dtr_usage == MOVED_DOWN ||
ap->rlsd_line_control == MOVED_DOWN)
/* dial has been requested _and_ the link is down */
{
tprintf("About to dial\n");
if (redial (ifp, filename) == 0) {
tprintf("Dial succeeded\n");
backoff = 4;
}
else {
if (backoff < 90000L) /* Max backoff is day & a bit */
backoff = backoff * 2;
tprintf("Dial failed, backing off for %lu seconds\n",
backoff);
}
}
alarm (backoff * 1000L);
if (pwait (& (ifp->supv)) == EABORT)
break;
alarm (0L);
ifp->dial_me = 0;
}
}
ifp->supv = NULLPROC;
tprintf("Demand dialing finished\n");
return 0;
}
/* get the number of pings before redialing (arg 4) */
if (argc < 5)
{
}
else if ((pings = atoi (argv[4])) <= 0)
{
tprintf ("pings must be > 0\n");
return 1;
}
/* retrieve the host name (arg 5) */
if (argc < 6)
{
}
else if ((target = resolve (argv[5])) == 0L)
{
tprintf (Badhost, argv[5]);
return 1;
}
countdown = pings;
ifp->supv = Curproc;
while (!main_exit)
{
int32 wait_for = interval;
if (ap->dtr_usage == FOUND_DOWN ||
ap->dtr_usage == MOVED_DOWN ||
ap->rlsd_line_control == MOVED_DOWN)
{
/* definitely down */
if (redial (ifp, filename) < 0)
break;
}
else if (ifp->lastrecv >= last_wait)
{
/* got something recently */
wait_for -= secclock () - ifp->lastrecv;
countdown = pings;
}
else if (countdown < 1)
{
/* we're down, or host we ping is down */
if (redial (ifp, filename) < 0)
break;
countdown = pings;
}
else if (target != 0L &&
(s = socket (AF_INET, SOCK_RAW, ICMP_PTCL)) != -1)
{
pingem (s, target, 0, (int16)s, 0);
close_s (s);
countdown--;
}
else if (ifp->echo != NULLFP)
{
(*ifp->echo) (ifp, NULLBUF);
countdown--;
}
last_wait = secclock ();
if (wait_for != 0L)
{
alarm (wait_for * 1000L);
if (pwait (& (ifp->supv)) == EABORT)
break;
alarm (0L); /* clear alarm */
}
} /* while (!main_exit) */
if (filename != argv[2])
free (filename);
ifp->supv = NULLPROC; /* We're being terminated */
return 0;
} /* int dodialer (argc, argv, p) */
/* execute dialer commands
* returns: -1 fatal error, 0 OK, 1 try again
*/
static int redial (ifp, file)
struct iface *ifp;
char *file;
{
char *inbuf, *intmp;
FILE *fp;
int (*rawsave) __ARGS ((struct iface *, struct mbuf *));
struct session *sp;
int result = 0;
int save_input = Curproc->input;
int save_output = Curproc->output;
unsigned i; /* loop counter */
if ((fp = fopen (file, READ_TEXT)) == NULLFILE)
{
tprintf ("redial: can't read %s\n", file);
return -1; /* Causes dialer proc to terminate */
}
/* Save output handler and temporarily redirect output to null */
if (ifp->raw == bitbucket)
{
tprintf ("redial: tip or dialer already active on %s\n", ifp->name);
(void) fclose (fp);
return -1;
}
/* allocate a session descriptor */
if (dial_inline == 0)
{
if ((sp = newsession (ifp->name, DIAL)) == NULLSESSION)
{
tprintf ("Too many sessions\n");
(void) fclose (fp);
return 1;
}
}
tprintf ("Dialing on %s\n\n", ifp->name);
/* Save output handler and temporarily redirect output to null */
rawsave = ifp->raw;
ifp->raw = bitbucket;
/* Suspend the packet input driver. Note that the transmit driver
* is left running since we use it to send buffers to the line.
*/
suspend (ifp->rxproc);
#ifdef notdef
tprintf ("rlsd: 0x%02x, dtr: 0x%02x\n",
Asy[ifp->dev].rlsd_line_control,
Asy[ifp->dev].dtr_usage);
#endif
inbuf = mallocw (BUFSIZ);
/* Read the file into cfg_cmd and exe_cmd. */
cfg_cmd = NULL;
exe_cmd = NULL;
cmd_ptr = cfg_cmd; /* initialize list pointer */
configuring = 0; /* not configuring yet */
while (fgets (inbuf, BUFSIZ, fp) != NULLCHAR)
{
if (strnicmp (inbuf, cfg_intro, strlen (cfg_intro)) == 0)
{
configuring = 1; /* found config section */
break;
}
}
if (configuring == 0)
{
tprintf ("redial: no \"configure:\" section\n");
(void) fclose (fp);
free (inbuf);
ifp->raw = rawsave;
resume (ifp->rxproc);
tprintf ("\nDial %s complete\n", ifp->name);
/* Wait for awhile, so the user can read the screen. */
#ifndef ATARI
Pause (10000L);
#endif
if (dial_inline == 0)
{
freesession (sp);
}
Curproc->input = save_input;
Curproc->output = save_output;
return (-1);
}
while (fgets (inbuf, BUFSIZ, fp) != NULLCHAR)
{
if (strnicmp (inbuf, exe_intro, strlen (exe_intro)) == 0)
{
configuring = 0; /* found execute section */
break;
}
if (*inbuf != '#' && *inbuf != '\n')
add_cmd (&cfg_cmd, &cmd_ptr, inbuf); /* add to list */
}
if (configuring == 1)
{
tprintf ("redial: no \"execute:\" section\n");
clean_up (); /* free list */
(void) fclose (fp);
free (inbuf);
ifp->raw = rawsave;
resume (ifp->rxproc);
tprintf ("\nDial %s complete\n", ifp->name);
/* Wait for awhile, so the user can read the screen. */
#ifndef ATARI
Pause (10000L);
#endif
if (dial_inline == 0)
{
freesession (sp);
}
Curproc->input = save_input;
Curproc->output = save_output;
return (-1);
}
cmd_ptr = exe_cmd; /* read in execute commands */
while (fgets (inbuf, BUFSIZ, fp) != NULLCHAR)
{
if (*inbuf != '#' && *inbuf != '\n')
add_cmd (&exe_cmd, &cmd_ptr, inbuf); /* add to list */
}
(void) fclose (fp);
intmp = mallocw (BUFSIZ);
/* Do the configure commands. */
cmd_ptr = cfg_cmd;
while (next_cmd (inbuf, &cmd_ptr) != NULLCHAR)
{
strcpy (intmp, inbuf);
rip (intmp);
log (-1, "%s dialer: %s", ifp->name, intmp);
if ((result = cmdparse (cfg_cmds, inbuf, ifp)) != 0)
{
tprintf ("\ninput line: %s\n", intmp);
break;
}
} /* while (next_cmd (inbuf, &cmd_ptr) != NULLCHAR) */
/* Do the execute commands. */
nr_ptr = number; /* initialize number pointer */
if (result == 0)
{
interrupted = 0;
for (i = 0; i < retries; i++)
{
if (pwait (NULL) == EABORT)
break; /* we are being killed */
cmd_ptr = exe_cmd;
while (next_cmd (inbuf, &cmd_ptr) != NULLCHAR)
{
int c; /* input character */
/* Poll the keyboard for 1/10 of a second to
* see if <ESC> has been pressed.
*/
if (dial_inline != 0)
{
alarm (100L);
if ((c = recvchar (Curproc->input)) != EOF)
{
alarm (0L);
recv_mbuf(Curproc->input,NULLBUFP,0,NULLCHAR,0);
if (c == 0x01b)
{
/* <ESC> pressed - give up. */
interrupted = 1;
result = -1;
tprintf ("interrupted\n");
break;
}
}
alarm (0L);
} /* if (dial_inline != 0) */
/* Process script command. */
strcpy (intmp, inbuf);
rip (intmp);
log (-1, "%s dialer: %s", ifp->name, intmp);
if ((result = cmdparse (dial_cmds, inbuf, ifp)) != 0)
{
tprintf ("\ninput line: %s\n", intmp);
break;
}
} /* while (next_cmd (inbuf, &cmd_ptr) != NULLCHAR) */
if (result == 0 || interrupted != 0)
break; /* dial succeeded */
} /* for (i = 0; i < retries; i++) */
} /* if (result == 0) */
clean_up (); /* free lists */
free (inbuf);
free (intmp);
if (result == 0)
{
ifp->lastsent = ifp->lastrecv = secclock ();
}
ifp->raw = rawsave;
resume (ifp->rxproc);
tprintf ("\nDial %s complete\n", ifp->name);
/* Wait for awhile, so the user can read the screen,
* AND to give it time to send some packets on the new connection!
*/
#ifndef ATARI
Pause (10000L);
#endif
if (dial_inline == 0)
{
freesession (sp);
}
Curproc->input = save_input;
Curproc->output = save_output;
return result;
} /* static int redial (ifp, file) */
static int dodial_control (argc, argv, p)
int argc;
char *argv[];
void *p;
{
struct iface *ifp = p;
int param;
if (ifp->ioctl == NULL)
return -1;
if ((param = devparam (argv[1])) == -1)
return -1;
(*ifp->ioctl) (ifp, param, TRUE, atol (argv[2]));
return 0;
} /* static int dodial_control (argc, argv, p) */
static int dodial_send (argc, argv, p)
int argc;
char *argv[];
void *p;
{
struct iface *ifp = p;
struct mbuf *bp;
if (argc > 2)
{
/* Send characters with inter-character delay
* (for dealing with prehistoric Micom switches that
* can't take back-to-back characters...yes, they
* still exist.)
*/
char *cp;
int32 cdelay = atol (argv[2]);
for (cp = argv[1];*cp != '\0';cp++)
{
bp = qdata (cp, 1);
asy_send (ifp->dev, bp);
Pause (cdelay);
}
}
else
{
bp = qdata (argv[1], strlen (argv[1]));
if (ifp->trace & IF_TRACE_RAW)
raw_dump (ifp, IF_TRACE_OUT, bp);
asy_send (ifp->dev, bp);
}
return 0;
} /* static int dodial_send (argc, argv, p) */
static int dodial_speed (argc, argv, p)
int argc;
char *argv[];
void *p;
{
struct iface *ifp = p;
if (argc < 2)
{
tprintf ("current speed = %u bps\n", Asy[ifp->dev].speed);
return 0;
}
return asy_speed (ifp->dev, (int16) atol (argv[1]));
} /* static int dodial_speed (argc, argv, p) */
/*
dodial_status - Bring interface up or down
*/
static int dodial_status (int argc, char *argv[], void *p)
{
struct iface *ifp = p;
int param;
if (ifp->iostatus == NULL)
return -1;
if ((param = devparam (argv[1])) == -1)
return -1;
/* (*ifp->iostatus) (ifp, param, atol (argv[2])); produces crash? */
(*ifp->iostatus) (ifp, param, 0);
return 0;
}
static int dodial_wait (argc, argv, p)
int argc;
char *argv[];
void *p;
{
struct iface *ifp = p;
register int c = -1;
alarm (atol (argv[1]));
if (argc == 2)
{
while ((c = asy_kb_poll (ifp->dev)) != -1)
{
tputc (c &= 0x7F);
tflush ();
}
alarm (0L);
return 0;
}
else
{
register char *cp = argv[2];
while (*cp != '\0' && (c = asy_kb_poll (ifp->dev)) != -1)
{
tputc (c &= 0x7F);
tflush ();
if (*cp++ != c)
{
cp = argv[2];
}
} /* while (*cp != '\0' && (c = asy_kb_poll (ifp->dev)) != -1) */
if (argc > 3)
{
if (stricmp (argv[3], "speed") == 0)
{
int16 speed = 0;
while ((c = asy_kb_poll (ifp->dev)) != -1)
{
tputc (c &= 0x7F);
tflush ();
if (isdigit (c))
{
speed *= 10;
speed += c - '0';
}
else
{
alarm (0L);
return asy_speed (ifp->dev, speed);
}
} /* while ((c = asy_kb_poll (ifp->dev)) != -1) */
} /* if (stricmp (argv[3], "speed") == 0) */
else
{
return -1;
}
} /* if (argc > 3) */
} /* if (argc != 2) */
alarm (0L);
return (c == -1);
} /* static int dodial_wait (argc, argv, p) */
/****************************************************************************
* cfg_init *
* Sets up the modem initialization string. *
****************************************************************************/
static int cfg_init (argc, argv, p)
int argc;
char **argv;
void *p;
{
if (init != NULL)
free (init);
if (strlen (argv[1]) == 0)
{
init = NULL;
return (0);
}
init = mallocw (strlen (argv[1]) + 1);
(void) strcpy (init, argv[1]);
return (0);
} /* static int cfg_init (argc, argv, p) */
/****************************************************************************
* cfg_dial_cmd *
* Sets up the modem dial command. *
****************************************************************************/
static int cfg_dial_cmd (argc, argv, p)
int argc;
char **argv;
void *p;
{
if (dial_cmd != NULL)
free (dial_cmd);
if (strlen (argv[1]) == 0)
{
dial_cmd = NULL;
return (0);
}
dial_cmd = mallocw (strlen (argv[1]) + 1);
(void) strcpy (dial_cmd, argv[1]);
return (0);
} /* static int cfg_dial_cmd (argc, argv, p) */
/****************************************************************************
* cfg_ld_code *
* Sets up the long distance code. *
****************************************************************************/
static int cfg_ld_code (argc, argv, p)
int argc;
char **argv;
void *p;
{
if (ld_code != NULL)
free (ld_code);
if (strlen (argv[1]) == 0)
{
ld_code = NULL;
return (0);
}
ld_code = mallocw (strlen (argv[1]) + 1);
(void) strcpy (ld_code, argv[1]);
return (0);
} /* static int cfg_ld_code (argc, argv, p) */
/****************************************************************************
* cfg_retries *
* Sets up the number of dial retries. *
****************************************************************************/
static int cfg_retries (argc, argv, p)
int argc;
char **argv;
void *p;
{
(void) sscanf (argv[1], "%u", &retries);
if (retries <= 0)
return (-1); /* must be >= 1 */
return (0);
} /* static int cfg_retries (argc, argv, p) */
/****************************************************************************
* cfg_number *
* Adds a number to the dial list. *
****************************************************************************/
static int cfg_number (argc, argv, p)
int argc;
char **argv;
void *p;
{
add_cmd (&number, &nr_ptr, argv[1]);
return (0);
} /* static int cfg_number (argc, argv, p) */
/****************************************************************************
* internal_send *
* Sends a string to dodial_send (). *
****************************************************************************/
static int internal_send (ptr, p)
char *ptr;
void *p;
{
char *argv[2];
argv[0] = NULL;
argv[1] = ptr;
return (dodial_send (2, argv, p));
} /* static int internal_send (ptr, p) */
/****************************************************************************
* dodial_init *
* Send the initialisation string to the modem. *
****************************************************************************/
static int dodial_init (argc, argv, p)
int argc;
char **argv;
void *p;
{
if (init == NULL)
return (0); /* no initialization string - ok */
return (internal_send (init, p));
} /* static int dodial_init (argc, argv, p) */
/****************************************************************************
* dodial_dial *
* Send the dialer commands and the next number to the modem. *
****************************************************************************/
static int dodial_dial (argc, argv, p)
int argc;
char **argv;
void *p;
{
char *buf; /* -> number buffer */
int rc; /* result code */
if (number == NULL)
return (-1); /* no numbers specified */
buf = mallocw (BUFSIZ); /* get a buffer for the number */
if (dial_cmd != NULL)
{
/* Send the dial command. */
if ((rc = internal_send (dial_cmd, p)) != 0)
{
free (buf);
return (rc);
}
} /* if (dial_cmd != NULL) */
if (ld_code != NULL)
{
/* Send the long distance code. */
if ((rc = internal_send (ld_code, p)) != 0)
{
free (buf);
return (rc);
}
} /* if (ld_code != NULL) */
/* Send the next number. */
if (next_cmd (buf, &nr_ptr) == NULLCHAR)
{
/* Try resetting the pointer. */
nr_ptr = number;
if (next_cmd (buf, &nr_ptr) == NULLCHAR)
{
free (buf); /* gone badly wrong */
return (-1);
}
} /* if (next_cmd (buf, nr_ptr) == NULLCHAR) */
if ((rc = internal_send (buf, p)) != 0) /* send the number */
{
free (buf);
return (rc);
}
rc = internal_send ("\r", p);
free (buf);
return (rc);
} /* static int dodial_dial (argc, argv, p) */
/****************************************************************************
* dodial_cwait *
* Conditional version of dodial_wait (). *
****************************************************************************/
static int dodial_cwait (argc, argv, p)
int argc;
char *argv[];
void *p;
{
struct iface *ifp = p;
register int c = -1;
int speedarg; /* index of "speed" argument */
int lastarg; /* index of last argument */
int i; /* loop counter */
char failed; /* failure flag - nz means failed */
alarm (atol (argv[1]));
lastarg = argc - 1;
if (stricmp (argv[lastarg], "speed") == 0)
{
speedarg = lastarg;
lastarg--;
}
else
speedarg = 0; /* no "speed" argument */
if (argc == 2)
{
/* Wait for duration expiry only. */
while ((c = asy_kb_poll (ifp->dev)) != -1)
{
tputc (c &= 0x7F);
tflush ();
}
alarm (0L);
return 0;
}
else
{
register char *cp = argv[2]; /* -> success string */
char **fail_ptr; /* array of ptrs to failure strings */
/* Set up the array of failure string pointers. */
fail_ptr = (char **) mallocw ((lastarg - 2) * sizeof (char *));
for (i = 0; i < (lastarg - 2); i++)
fail_ptr[i] = argv[i + 3];
/* Looking for string matches. */
failed = 0;
while ((c = asy_kb_poll (ifp->dev)) != -1)
{
tputc (c &= 0x7F);
tflush ();
/* Check the success string first. */
if (*cp == '\0')
break; /* we got a connect */
if (*cp++ != c)
{
cp = argv[2];
}
/* Now check the failure strings. */
for (i = 0; i < (lastarg - 2); i++)
{
if (*fail_ptr[i] == '\0')
{
failed = 1;
break; /* we lost */
}
if (*fail_ptr[i]++ != c)
{
fail_ptr[i] = argv[i + 3];
}
}
if (failed)
break;
} /* while ((c = asy_kb_poll (ifp->dev)) != -1) */
free (fail_ptr); /* give back heap memory */
/* If we get here, we may have matched the "success" string. */
if (*cp != '\0')
{
alarm (0L);
return (-1); /* we didn't */
}
if (speedarg != 0)
{
int16 speed = 0;
while ((c = asy_kb_poll (ifp->dev)) != -1)
{
tputc (c &= 0x7F);
tflush ();
if (isdigit (c))
{
speed *= 10;
speed += c - '0';
}
else
{
alarm (0L);
return asy_speed (ifp->dev, speed);
}
} /* while ((c = asy_kb_poll (ifp->dev)) != -1) */
} /* if (stricmp (lastarg, "speed") == 0) */
} /* if (argc != 2) */
alarm (0L);
return (c == -1);
} /* static int dodial_cwait (argc, argv, p) */
/****************************************************************************
* add_cmd *
* Add a string to the end of the list whose header is pointed to by *
* <*hdr>. <*ptr> (if non-NULL) points to the last item in the list. *
* <buf> points to the data to be added to the list and is assumed to be *
* an ASCIIZ string. *
****************************************************************************/
static void add_cmd (hdr, ptr, buf)
ITEM **hdr;
ITEM **ptr;
char *buf;
{
if (strlen (buf) == 0)
return;
if (*hdr == NULL)
{
/* Empty list. */
*hdr = (ITEM *) mallocw (sizeof (ITEM));
*ptr = *hdr;
}
else
{
(*ptr)->next = (ITEM *) mallocw (sizeof (ITEM));
*ptr = (*ptr)->next;
}
(*ptr)->data = (char *) mallocw (strlen (buf) + 1);
(*ptr)->next = NULL;
(void) strcpy ((*ptr)->data, buf);
} /* static void add_cmd (hdr, ptr, buf) */
/****************************************************************************
* next_cmd *
* Copies the data part of the item pointed to by <*ptr> into the buffer *
* pointed to by <buf>. This area is assumed to be large enough to hold *
* the data. <*ptr> is advanced to point to the next item. Returns <buf> *
* if there is another item, NULLCHAR at the end of the list. *
****************************************************************************/
static char *next_cmd (buf, ptr)
char *buf;
ITEM **ptr;
{
if (*ptr == NULL)
return (NULLCHAR);
(void) strcpy (buf, (*ptr)->data);
*ptr = (*ptr)->next;
return (buf);
} /* static char *next_cmd (buf, ptr) */
/****************************************************************************
* clean_up *
* Frees the heap memory used by the various lists. *
****************************************************************************/
static void clean_up ()
{
clean (&number);
clean (&cfg_cmd);
clean (&exe_cmd);
if (init != NULL)
{
free (init);
init = NULL;
}
if (dial_cmd != NULL)
{
free (dial_cmd);
dial_cmd = NULL;
}
if (ld_code != NULL)
{
free (ld_code);
ld_code = NULL;
}
retries = 1;
} /* static void clean_up () */
/****************************************************************************
* clean *
* Free up the list pointed to by <*hdr>. *
****************************************************************************/
static void clean (hdr)
ITEM **hdr;
{
ITEM *p, *q; /* list followers */
p = *hdr;
while (p != NULL)
{
q = p->next;
free (p->data);
free (p);
p = q;
}
*hdr = NULL;
} /* static void clean (hdr) */
/****************************************************************************
* asy_kb_poll *
* Polls the async interface for incoming characters and the keyboard for *
* <ESC>. Returns the character on the async receive queue or -1 if timed *
* out or <ESC> detected. *
****************************************************************************/
static int asy_kb_poll (dev)
int dev;
{
int c; /* input character */
for (;;)
{
/* Check keyboard. */
if (socklen (Curproc->input,0) > 0)
{
c = recvchar (Curproc->input);
if (c != EOF)
{
recv_mbuf (Curproc->input, NULLBUFP, 0, NULLCHAR, 0);
if (c == 0x1b)
{
/* <ESC> pressed - give up. */
interrupted = 1;
c = -1;
break;
}
} /* if (c != EOF) */
} /* if (socklen (Curproc->input,0) > 0) */
/* Check async. */
if (asy_len (dev) > 0)
{
c = get_asy (dev);
break;
}
/* Let someone else run. */
if (pwait (0) != 0)
{
c = -1;
break;
}
} /* for (;;) */
return (c);
} /* static int asy_kb_poll (dev) */